﻿using Microsoft.Extensions.DependencyInjection;
using PMS.Core.Infrastructure;
using PMS.Core.Utils.Http;
using PMS.Data.Entities.ScheduleTasks;
using PMS.Services.EntityServices.Logging;
using PMS.Services.SharedKernel;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace PMS.Services.Utils.ScheduleTasks
{
    //// <summary>
    /// DavidLee 2020/06/22 使用Quartz.NET重新实现定时任务功能，支持Cron表达式
    /// </summary>
    [DisallowConcurrentExecution]
    public partial class TaskThread : IJob
    {
        #region Fields
        /// <summary>
        /// 一个线程任务(Job)对应一个任务记录
        /// </summary>
        private SystemScheduleTask _task;
        private static readonly string _scheduleTaskUrl;
        #endregion

        #region Ctor
        public TaskThread()
        {
        }
        static TaskThread()
        {
            _scheduleTaskUrl = $"{EngineContext.Current.Resolve<IStoreContext>().CurrentStore.Url}{ScheduleTaskDefaultConfigs.ScheduleTaskPath}";
        }
        #endregion

        #region override
        public Task Execute(IJobExecutionContext context)
        {

            AbstractTrigger trigger = (context as JobExecutionContextImpl).Trigger as AbstractTrigger;
            HttpClient client = null;
            try
            {
                if(_task != null)
                {
                    if(!_task.TaskName.Equals(trigger.JobKey.Name, StringComparison.OrdinalIgnoreCase)
                     &&!_task.GroupName.Equals(trigger.JobKey.Name, StringComparison.OrdinalIgnoreCase) )
                        _task = null;
                } //Do not use if/else
                if (_task == null)
                {
                    var taskManager = TaskManager.Instance;
                    _task = taskManager.Tasks.FirstOrDefault(x => x.TaskName == trigger.JobKey.Name && x.GroupName == trigger.JobKey.Group)
                          ?? taskManager.Tasks.FirstOrDefault(x => x.TaskName == trigger.JobName && x.GroupName == trigger.JobGroup);
                }
                if (_task == null)
                    throw new TaskCanceledException(string.Format(SystemScheduleTaskMessage.ScheduleTasksErrorOnRequest, trigger.Name, trigger.Group, "未找到任务数据或可能被移除"));
                //Console.WriteLine($"自动计划任务[{_task.TaskName}]开始:{ DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss")}");
                //create and configure client
                client = EngineContext.Current.Resolve<IHttpClientFactory>().CreateClient(HttpDefaultConfigs.DefaultHttpClient);
                //DavidLee 2019/11/24 HttpClient.TimeOut Must!!! Not less or equal than 0
                if(_task.RunTimeOut.HasValue)
                    client.Timeout = TimeSpan.FromMilliseconds(_task.RunTimeOut.Value <= 60 ? 60 : _task.RunTimeOut.Value);
                //send post data
                var data = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("taskType", _task.Type) });
                client.PostAsync(_scheduleTaskUrl, data).Wait();
            }
            catch (Exception ex)
            {
                var _serviceScopeFactory = EngineContext.Current.Resolve<IServiceScopeFactory>();
                using (var scope = _serviceScopeFactory.CreateScope())
                {
                    // Resolve
                    var logger = scope.ServiceProvider.GetRequiredService<ILogger>();
                    logger.Error(ex.Message);
                }
            }
            finally
            {
                //_task = null;  //Important!!! set null to release cache
                if (client != null)
                {
                    client.Dispose();
                    client = null;
                }
            }
            return Task.CompletedTask;
        }
        #endregion
    }
}
